iT邦幫忙

1

Rails基本介紹(三)--Migration簡單操作

  • 分享至 

  • xImage
  •  

Yes

週一,要裝得認真點~


本篇會說到的。

  1. Why?
  2. 名詞單數複數查詢。
  3. Migration。

為何還需要再次瞭解這個Rails中很基本的部分?

基本上開發伴隨著Git版控已經是常見的事,但Git控制著的是Project的版本,對於資料庫不會操作到。

如果我們建立了Migrate檔案並執行後,

$ rails db:migrate

Rails會將裡面內容輸入對應資料庫並記錄,即使手動刪除或使用

$ rails db:rollback
$ rails db:rollback SETP=?       ?號代表回覆幾步。

等指令倒退後再刪除,DB內已經建立欄位,要再次輸入同名欄位或table就會有被阻止的況狀。
因此開發中更改table時,需要有正確的流程,避免table無法順利更新等狀況。

正確使用Migrate很繁瑣,但是很安全。


單複數查詢

英文不好的我,覺得這兩個語法很重要,製作Model,Controller可以少一點時間查字典。

#irb
2.7.3 :002 > require 'active_support/inflector'
2.7.3 :005 > puts "player".pluralize
players
 => nil 
2.7.3 :006 > puts "players".singularize
player

Migration

首先打開專案,進到DB資料夾。
https://ithelp.ithome.com.tw/upload/images/20210817/20135887UdX8jESwRW.png
我們會說到的部分以開發工具會看到的部分做說明。
https://ithelp.ithome.com.tw/upload/images/20210817/20135887jWSAVK78tr.png

我們先建立一個model,請注意我故意Model名輸入複數。

$ rails g model players name age:integer homeland
Running via Spring preloader in process 15399
[WARNING] The model name 'players' was recognized as a plural, using the singular 'player' instead. Override with --force-plural or setup custom inflection rules for this noun before running the generator.
      invoke  active_record
      create    db/migrate/20210817060308_create_players.rb
      create    app/models/player.rb
      invoke    test_unit
      create      test/models/player_test.rb
      create      test/fixtures/players.yml

我們先看。

[WARNING] The model name 'players' was recognized as a plural, using the singular 'player' instead. Override with --force-plural or setup custom inflection rules for this noun before running the generator.

雖然框架已經進化到會幫你改單數,但還是請依照單複數正確操作,避免意外,一樣test部分我們先略。
看看今天的主角群之一20210817060308_create_players.rb這檔案。

class CreatePlayers < ActiveRecord::Migration[6.1]
  def change
    create_table :players do |t|
      t.string :name
      t.integer :age
      t.string :homeland

      t.timestamps
    end
  end
end

養成習慣執行migrate前,檢查檔案內容。
可以發現name,homeland我沒有輸入string,代表指令可省略string這個與設值,還有沒有其他可省略我不會去記,我只會記如果檢查有問題,直接這個檔案做修改就可以。

指令只是幫你做出這個編碼表格,還沒有正式幫你建立資料庫。

為了操作,我們先將age的與設值也改一下。

t.string :age

存擋後執行

$ rails db:migrate
== 20210817060308 CreatePlayers: migrating ====================================
-- create_table(:players)
   -> 0.0015s
== 20210817060308 CreatePlayers: migrated (0.0016s) ===========================

可以看到schema.rb長出資料了。

  create_table "players", force: :cascade do |t|
    t.string "name"
    t.string "age"
    t.string "homeland"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
  end
# create_table,新建table

這代表資料庫(模式)已經建立,請記得一件事,不要手動裡面任何一個字,由Migration來幫你處理。
不要手動修改schema.rb的資料。

create_table,就是第一個常用指令,建立資料表。

改單一欄位資料型態change_column

我後悔了age我還是想用integer型態紀錄。
建立migration,以下兩個指令請都依序輸入。

$ rails g migration player
$ rails g migration player_change_age_integer

新的migrate檔案依序長得如下

class Player < ActiveRecord::Migration[6.1]
  def change
  end
end

class PlayerChangeAgeInteger < ActiveRecord::Migration[6.1]
  def change
  end
end

不一樣的地方只有class名,這也代表migration後面的成為class名,類別無法重複,所以當建立migrate檔案時,migration後面請好好確定,不然也會遇到卡住的狀況。
自己選一個刪掉吧,也只有這時能手動刪migrate檔案。(未執行rails db:migrate前)

class PlayerChangeAgeInteger < ActiveRecord::Migration[6.1]
  def change
    change_column :players, :age, :integer
  end
end

#改變欄位 :哪張資料表, :哪一欄名, :改變內容(這次是型態)

執行

$ rails db:migrate

回到schema.rb。可以發現age欄位的改變。

  create_table "players", force: :cascade do |t|
    t.string "name"
    t.integer "age"
    t.string "homeland"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
  end

改單一欄位名 rename_column

$ ails g migration players_name_to_nickname

class PlayersNameToNickname < ActiveRecord::Migration[6.1]
  def change
  end
end

class PlayersNameToNickname < ActiveRecord::Migration[6.1]
  def change
    rename_column :players, :name, :nickname
  end
end
# 單一欄位改名 :table_name, old_name, new_name

如果無誤,schema.rb如下

  create_table "players", force: :cascade do |t|
    t.string "nickname"
    t.integer "age"
    t.string "homeland"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
  end

如果一次想三個都改。

修改資料表欄位change_table

$ rails g migration players_three_columns
#格式如下
def change
  change_table :table_name do |t|
    t.rename :old_column1, :new_column1
    t.rename :old_column2, :new_column2
    ...
  end
end
  
#示範
def change
  change_table :players do |t|
    t.rename :nickname, :name
    t.rename :age, :power
    t.rename :homeland, :country
  end
end

如無誤,schema.rb應該如下

create_table "players", force: :cascade do |t|
  t.string "name"
  t.integer "power"
  t.string "country"
  t.datetime "created_at", precision: 6, null: false
  t.datetime "updated_at", precision: 6, null: false
end

增加欄位add_column

$ rails g migration player_add_column_level

#格式
class PlayerAddColumnLevel < ActiveRecord::Migration[6.1]
  def change
    add_column :table_name, :new_column, :type, :options
  end
end

#option部分可以想成額外帶入一些設定,例如是否為唯一(uniq),可否空白,預設值,此部分操作與設值。
#option可以不只一個。
#本次操作
def change
  add_column :players, :level, :integer, :default => 1
end

如正確schema.rb如下

create_table "players", force: :cascade do |t|
  t.string "name"
  t.integer "power"
  t.string "country"
  t.datetime "created_at", precision: 6, null: false
  t.datetime "updated_at", precision: 6, null: false
  t.integer "level", default: 1
end
#這邊也應該發現,在schema中,一直都是create_table。

補充修改預設

$ rails g migration players_level_default

class PlayersLevelDefault < ActiveRecord::Migration[6.1]
  def change
    change_column_default :players, :level, 2
  end
end
#change_column_default :table_name, :column_name, default_value
#當然預設條件不只一種,會有其他變化。

#schema.rb
  create_table "players", force: :cascade do |t|
    t.string "name"
    t.integer "power"
    t.string "country"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
    t.integer "level", default: 2
  end

移除欄位remove_column

操作與add_column,不操作了。

  remove_column :table_name, :column_name

移除資料表drop_table

  drop_table :table_name

修改資料表名稱rename_table

  rename_table :table_name, :old_name, :new_name

資料表刪除與改名,如果共同開發,不大可能是輕易決定。操作方式大同小異。
新手初期應該是在修改預設值,uniq等部分會先卡住一下下。

整理一下

Table相關

新增資料表create_table
移除資料表drop_table
修改資料表名稱rename_table
修改資料表欄位change_table

Column相關

新增一個欄位add_column
修改欄位名稱rename_column
修改欄位的型態(type)change_column
移除欄位remove_column
change_column_default

當然有更多的指令,要熟練當然只能查手冊與多練習,反正rails new很便宜....
Active Record Migrations

新增、移除索引,重要到等關聯性再說明。

另外如果自己查資料,看到self.up或down等語法,那屬於舊版本操作,以目前開發,會少用到。


分享一個邏輯笑話

老婆: 老公,你覺得家花香還是野花香?
老公: 當然是家花!
老婆: 你一定嘗過野花,才知道家花香!
好,我笑點低


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言